using System;
using System.Reflection;
using ValidationFramework;

namespace QSBusinessLayerCSharp
{

    public class Person : NotifyValidatableBase
    {

        #region Fields

        //Define run-time constants here so UI code has compile-time
        //checks against misspellings in data binding expressions.
        public const string FirstNameMember = "FirstName";
        public const string GenderMember = "Gender";
        public const string AddressMember = "Address";
        public const string LastNameMember = "LastName";
        public const string AgeMember = "Age";
        public const string EmailAddressMember = "EmailAddress";
        public const string CardTypeMember = "CardType";
        public const string CreditCardNumberMember = "CreditCardNumber";
        public const string OrderTotalMember = "OrderTotal";
        public const string PhoneNumberMember = "PhoneNumber";

        private Address address;
        private string firstName;
        private string lastName;
        private string phoneNumber;
        private int age;
        private string emailAddress;
        private CardType? cardType;
        private string creditCardNumber;
        private decimal orderTotal;
        private Gender gender;

        #endregion

        #region Constructor

        public Person()
		{
			PropertyValidationManager.ValidateAll();
        }


        #endregion

        #region Properties

		[IsValidValidatorAttribute]
        public Address Address
        {
            get
            {
                return address;
            }
            set
            {
				if (value != address)
                {
					address = value;
					NotifyPropertyChanged(AddressMember);
                }
            }
        }

        [RequiredStringRule]
        [RequiredStringRule(InitialValue = "aaa", IgnoreCase = true, TrimWhiteSpace = false)]
        [LengthStringRule(50)]
        public string FirstName
        {
            get
            {
                return firstName;
            }
            set
            {
                if (value != firstName)
                {
                    firstName = value;
                    NotifyAndValidate(FirstNameMember);
                }
            }
        }

        [RequiredStringRule]
        [LengthStringRule(50, Minimum = 2)]
        public string LastName
        {
            get
            {
                return lastName;
            }
            set
            {
                if (value != lastName)
                {
                    lastName = value;
                    NotifyAndValidate(LastNameMember);
                }
            }
        }

        [RequiredIntRule]
        [CompareIntRule(18, CompareOperator.GreaterThanEqual)]
        [CompareIntRule(100, CompareOperator.LessThanEqual)]
        public int Age
        {
            get
            {
                return age;
            }
            set
            {
                if (value != age)
                {
                    age = value;
                    NotifyAndValidate(AgeMember);
                }
            }
        }

        [RequiredStringRule]
        [RegexValidatorAttribute(@"\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", ErrorMessage = "Invalid email format.")]
        [LengthStringRule(50)]
        public string EmailAddress
        {
            get
            {
                return emailAddress;
            }
            set
            {
                if (value != emailAddress)
                {
                    emailAddress = value;
                    NotifyAndValidate(EmailAddressMember);
                }
            }
        }


		[RequiredEnumRule((long)QSBusinessLayerCSharp.CardType.Visa)]
        public CardType? CardType
        {
            get
            {
                return cardType;
            }
            set
            {
                if (value != cardType)
                {
                    cardType = value;
                    NotifyAndValidate(CardTypeMember);
                    NotifyAndValidate(CreditCardNumberMember);
                }
            }
        }

        [RequiredStringRule]
        [LengthStringRule(16)]
        [InlineValidatorAttribute("QSBusinessLayerCSharp.Person,QSBusinessLayerCSharp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "CheckValidCreditCard", "Validate based on credit card rules.", ErrorMessage = "Credit card is invalid.")]
        public string CreditCardNumber
        {
            get
            {
                return creditCardNumber;
            }
            set
            {
                if (value != creditCardNumber)
                {
                    creditCardNumber = value;
                    NotifyAndValidate(CreditCardNumberMember);
                }
            }
        }

        [RequiredDecimalRule]
        [RangeDecimalRule(10, 1000)]
        public decimal OrderTotal
        {
            get
            {
                return orderTotal;
            }
            set
            {
                if (value != orderTotal)
                {
                    orderTotal = value;
                    NotifyAndValidate(OrderTotalMember);
                }
            }
        }


        [RegexValidatorAttribute(@"\d{2}-\d{4}-\d{4}", ErrorMessage = "Phone number must be of the format 11-1111-1111")]
        public string PhoneNumber
        {
            get
            {
                return phoneNumber;
            }
            set
            {
                if (value != phoneNumber)
                {
                    phoneNumber = value;
                    NotifyAndValidate(PhoneNumberMember);
                }
            }
        }

        public int Id { get; set; }


        [RequiredEnumRule((long)Gender.Unknown)]
        public Gender Gender
        {
            get
            {
                 return gender;
            }
            set
            {
                if (value != gender)
                {
                    gender = value;
                    NotifyAndValidate(GenderMember);
                }
            }
        }

        #endregion

        #region Methods

        public static void CheckValidCreditCard(object sender, CustomValidationEventArgs e)
        {
            var person = (Person)e.TargetObjectValue;
            var cardType = person.CardType;
            var cardNumber = person.CreditCardNumber;
            if (cardNumber == null || cardType == null)
            {
                e.IsValid = false;
            }
            else
            {
                switch (cardType.Value)
                {
                    case QSBusinessLayerCSharp.CardType.Visa:
                    case QSBusinessLayerCSharp.CardType.MasterCard:
                        {
                            e.IsValid = (cardNumber.Length == 16);
                            e.ErrorMessage = "VISA/MasterCard has to have 16 characters";
                            break;
                        }
                    case QSBusinessLayerCSharp.CardType.Amex:
                        {
                            e.IsValid = (cardNumber.Length == 15);
                            e.ErrorMessage = "AMEX has to have 15 characters.";
                            break;
                        }
                    default:
                        {
                            throw new ArgumentException("Invalid CardType");
                        }
                }
            }
        }


        public void Hello([RequiredStringRule]string text)
        {
            var validate = ParameterValidationManager.Validate(this, MethodBase.GetCurrentMethod().MethodHandle, text);
        }

        #endregion

    }
}